﻿using System;
using System.Collections.Generic;
using System.Security;
using System.Security.Permissions;
using System.Runtime.Serialization;
using Light.Framework.Contract;

namespace Light.Framework
{

    [Serializable]
    public class AccessPermission : IPermission, IUnrestrictedPermission
    {
        private bool _unrestricted = true;
        private string _taskCodes = null;
        private bool _demandAll = false;

        public AccessPermission(bool unrestricted, string taskCodes)
        {
            this._unrestricted = unrestricted;
            this._taskCodes = taskCodes;

        }

        public AccessPermission(bool unrestricted, string taskCodes, bool demandAll)
            : this(unrestricted, taskCodes)
        {
            this._demandAll = demandAll;
        }

        public AccessPermission(PermissionState state)
        {
            _unrestricted = (state == PermissionState.Unrestricted);
        }

        #region IPermission Members

        public IPermission Copy()
        {
            return new AccessPermission(this._unrestricted, this._taskCodes);
        }

        public virtual void Demand()
        {
            IUser user = ServerApplication.User;
            if (user == null)
                throw new AccessSecurityException("登录超时，请重新登录。");

            if (!String.IsNullOrEmpty(_taskCodes))
            {
                string[] taskCodes = _taskCodes.Split(new char[] { System.IO.Path.PathSeparator });

                int cntTotal = 0;
                List<string> taskDescs = new List<string>();

                foreach (var taskCode in taskCodes)
                {
                    if (user.HasRight(taskCode))
                    {
                        if (_demandAll)
                            cntTotal++;
                        else
                            return;
                    }
                    else
                    {
                        taskDescs.Add(taskCode);
                    }
                }
                if (cntTotal == taskCodes.Length)
                    return;

                throw new AccessSecurityException("用户 (" + user.Name + ") 访问已被拒绝，需要获得权限 [" + string.Join("、", taskDescs.ToArray()) + "]");
            }
        }

        public bool IsSubsetOf(IPermission target)
        {
            return false;
        }

        public IPermission Intersect(IPermission target)
        {
            return null;
        }

        public IPermission Union(IPermission target)
        {
            return null;
        }

        #endregion

        #region ISecurityEncodable Members

        public void FromXml(SecurityElement elem)
        {
            if (elem == null)
                throw new ArgumentNullException("elem");

            string flag = elem.Attribute("Unrestricted");
            if (flag != null)
                this._unrestricted = bool.Parse(flag);

            flag = elem.Attribute("TaskCodes");
            if (flag != null)
                _taskCodes = flag;
        }

        public SecurityElement ToXml()
        {
            SecurityElement elem = new SecurityElement("IPermission");

            elem.AddAttribute("class", this.GetType().AssemblyQualifiedName);
            elem.AddAttribute("version", "1");

            elem.AddAttribute("Unrestricted", this._unrestricted.ToString());
            if (_taskCodes != null)
                elem.AddAttribute("TaskCodes", _taskCodes);

            return elem;
        }

        #endregion

        #region IUnrestrictedPermission Members

        public bool IsUnrestricted()
        {
            return this._unrestricted;
        }

        #endregion
    }

    /// <summary>
    /// AccessSecurityException 的摘要说明。
    /// </summary>
    [Serializable()]
    [SecurityPermission(SecurityAction.LinkDemand, SerializationFormatter = true)]
    public class AccessSecurityException : SecurityException
    {
        public AccessSecurityException(string message)
            : base(message)
        {
        }

        public AccessSecurityException()
            : base("因为违背安全策略或将要执行的操作未获授权，用户访问已被拒绝。")
        {
        }

        public AccessSecurityException(Exception inner)
            : base("因为违背安全策略或将要执行的操作未获授权，用户访问已被拒绝。", inner)
        {
        }

        public AccessSecurityException(string message, Exception inner)
            : base(message, inner)
        {
        }

        protected AccessSecurityException(SerializationInfo info, StreamingContext context)
            : base(info, context)
        {
        }
    }
}
